package db

import (
	"database/sql"
	"strings"

	"github.com/pkg/errors"
	"gorm.io/driver/mysql"
	"gorm.io/driver/postgres"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/schema"

	"{{filepathJoin .ModName "internal/pkg/conf"}}"
	"{{filepathJoin .ModName "internal/pkg/log"}}"
)

var db *gorm.DB

// Init 函数用于初始化数据库连接
func Init() error {
	// 声明一个 gorm.Dialector 类型的变量，用于后续的数据库连接
	var dialector gorm.Dialector
	// 从配置中获取数据库连接字符串
	dsn := conf.GetString("db.dsn")
	// 如果 dsn 为空，则返回错误提示
	if dsn == "" {
		return errors.New("db.dsn must be set")
	}

	// 根据配置中的 db.type 来选择使用哪种数据库
	switch strings.ToLower(conf.GetString("db.type")) {
	case "sqlite", "":
		dialector = sqlite.Open(dsn)
	case "mysql":
		dialector = mysql.Open(dsn)
	case "postgres", "pgsql":
		dialector = postgres.Open(dsn)
	default:
		// 如果是不支持的类型，则返回错误提示
		return errors.New("unknown db type")
	}

	// 使用 gorm.Open 尝试建立数据库连接
	var err error
	db, err = gorm.Open(dialector, &gorm.Config{
		Logger: log.NewLogger(), // 设置日志记录器
		NamingStrategy: schema.NamingStrategy{
			TablePrefix: conf.GetString("db.prefix"), // 设置表前缀
			//SingularTable: true, // 禁用表名复数，此处在注释状态，可根据需要取消注释启用
		},
	})

	// 如果连接失败，则包装错误并返回
	if err != nil {
		return errors.Wrap(err, "failed to connect database")
	}

	// 返回 nil 表示初始化成功
	return nil
}

// Instance 获取数据库实例
//
//	@return *gorm.DB
func Instance() *gorm.DB {
	// [user]:[password]@tcp(127.0.0.1:3306)/[dbname]?charset=utf8mb4&parseTime=True&loc=Local
	return db
}

// AutoMigrate 函数用于自动迁移数据库模式以匹配给定的模型。
// 如果数据库连接未初始化（db 为 nil），则返回错误。
func AutoMigrate(values ...any) error {
	// 检查数据库连接是否为 nil
	if db == nil {
		return errors.New("db is nil")
	}

	// 使用 gorm 的 AutoMigrate 方法进行数据库模式迁移
	return db.AutoMigrate(values...)
}

// Transaction 开启事务
//
//	@param fc
//	@param opts
//	@return error
func Transaction(fc func(tx *gorm.DB) error, opts ...*sql.TxOptions) error {
	return db.Transaction(fc, opts...)
}
